package oa.hleast.xswl.service.banner.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import oa.hleast.common.constant.CommonConstant;
import oa.hleast.common.constant.ConfigKeyConstant;
import oa.hleast.common.redis.component.template.RedisRepository;
import oa.hleast.common.result.Result;
import oa.hleast.common.web.exception.BizException;
import oa.hleast.xswl.common.enums.BannerShowStatusEnum;
import oa.hleast.xswl.mapper.WebsiteBannerMapper;
import oa.hleast.xswl.pojo.domain.SysDictItem;
import oa.hleast.xswl.pojo.domain.banner.CmsWebsiteBanner;
import oa.hleast.xswl.pojo.form.banner.CmsWebsiteBannerForm;
import oa.hleast.xswl.pojo.vo.web.CmsWebsiteBannerVo;
import oa.hleast.xswl.pojo.vo.web.HomePageWebsiteBannerVo;
import oa.hleast.xswl.service.ISysDictItemService;
import oa.hleast.xswl.service.banner.IWebsiteBannerService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 302
 * @description
 * @date 2021/3/12
 */

@Transactional
@Slf4j
@Service
@AllArgsConstructor
public class WebsiteBannerServiceImpl extends ServiceImpl<WebsiteBannerMapper, CmsWebsiteBanner> implements IWebsiteBannerService {

    private final RedisRepository redisRepository;
    private final ISysDictItemService dictItemService;


    @Override
    public HomePageWebsiteBannerVo getStartUpData() {
        //从数据库中取数据
        log.info("启动页数据，从数据库中获取");
        Page<HomePageWebsiteBannerVo> homePageVoPage = getWebsiteBannerPageByKey(1, 1, ConfigKeyConstant.HOME_PAGE_START_UP_KEY);
        return homePageVoPage.getRecords().get(0);
    }

    @Override
    public Page<HomePageWebsiteBannerVo> getHomePageServerWebsiteBanner(Integer page, Integer limit) {
        //从数据库中取数据
        log.info("服务页轮播图数据，从数据库中获取");
        Page<HomePageWebsiteBannerVo> homePageVoPage = getWebsiteBannerPageByKey(page, limit, ConfigKeyConstant.HOME_PAGE_SERVER_WEBSITE_BANNER_KEY);
        log.info("homePageVoPage = {}", homePageVoPage);
        return homePageVoPage;
    }

    @Override
    public Page<HomePageWebsiteBannerVo> getHomePageMallWebsiteBanner(Integer page, Integer limit) {
        //从数据库中取数据
        log.info("服务页轮播图数据，从数据库中获取");
        Page<HomePageWebsiteBannerVo> homePageVoPage = getWebsiteBannerPageByKey(page, limit, ConfigKeyConstant.HOME_PAGE_MALL_WEBSITE_BANNER_KEY);
        log.info("homePageVoPage = {}", homePageVoPage);
        return homePageVoPage;
    }

    @Override
    public Page<HomePageWebsiteBannerVo> getHomePageWebsiteBanner(Integer page, Integer limit) {
        //从数据库中取数据
        log.info("首页轮播图数据，从数据库中获取");
        Page<HomePageWebsiteBannerVo> homePageVoPage = getWebsiteBannerPageByKey(page, limit, ConfigKeyConstant.HOME_PAGE_WEBSITE_BANNER_KEY);
        log.info("homePageVoPage = {}", homePageVoPage);
        return homePageVoPage;
    }

    @Override
    public Page<HomePageWebsiteBannerVo> getWuchengWebsiteBannerPage(Integer page, Integer limit) {
        log.info("婺城概貌轮播图数据，从数据库中获取");
        Page<HomePageWebsiteBannerVo> voPage = getWebsiteBannerPageByKey(page, limit, ConfigKeyConstant.HOME_PAGE_WUCHENG_WEBSITE_BANNER_KEY);
        log.info("voPage = {}", voPage);
        return voPage;
    }

    @Override
    public Page<HomePageWebsiteBannerVo> getWebsiteBannerPageByKey(Integer page, Integer limit, String configKey) {
        Long dictPositionTypeId = dictItemService.getDictItemByConfigKey(configKey).getId();
        return getWebsiteBannerPage(page, limit, dictPositionTypeId);
    }

    @Override
    public boolean add(CmsWebsiteBannerForm websiteBannerForm) {

        //校验位置信息 并返回字典信息
        SysDictItem sysDictItem = checkAndGetPosition(websiteBannerForm.getDictPositionTypeId());
        //校验上架时间 < 下架时间
        checkTime(websiteBannerForm);

        CmsWebsiteBanner cmsWebsiteBanner = conversionToPojo(websiteBannerForm);

        if (ObjectUtils.isEmpty(cmsWebsiteBanner)) {
            throw new BizException("参数错误");
        }
        cmsWebsiteBanner.setDictPositionTypeId(sysDictItem.getId());

        return this.save(cmsWebsiteBanner);
    }

    @Override
    public Page<CmsWebsiteBannerVo> pageList(Integer page, Integer limit, String title, Integer showStatus, Long dictPositionTypeId) {
        log.error("title = {},  showStatus = {},  dictPositionTypeId = {}", title, showStatus, dictPositionTypeId);
        LambdaQueryWrapper<CmsWebsiteBanner> queryWrapper = new LambdaQueryWrapper<CmsWebsiteBanner>()
                .eq(CmsWebsiteBanner::getDeleted, 0)
                .orderByAsc(CmsWebsiteBanner::getSort)
                .orderByDesc(CmsWebsiteBanner::getGmtModified)
                .orderByDesc(CmsWebsiteBanner::getGmtCreate);

        //各条件的查询
        if (ObjectUtils.isNotEmpty(dictPositionTypeId)) {
            queryWrapper.eq(CmsWebsiteBanner::getDictPositionTypeId, dictPositionTypeId);
        }

        if (StringUtils.isNotBlank(title)) {
            queryWrapper.like(CmsWebsiteBanner::getTitle, title);
        }
        if (ObjectUtils.isNotEmpty(showStatus)) {

            long nowTime = System.currentTimeMillis();

            BannerShowStatusEnum showStatusEnum = BannerShowStatusEnum.getValue(showStatus);
            switch (Objects.requireNonNull(showStatusEnum)) {
                case SHOWING:
                    //展示中 开始时间小于等于当前时间，结束时间大于当前时间
                    queryWrapper.le(CmsWebsiteBanner::getStartTime, nowTime);
                    queryWrapper.gt(CmsWebsiteBanner::getEndTime, nowTime);
                    break;
                case EXPIRED:
                    //已过期 结束时间小于当前时间
                    queryWrapper.lt(CmsWebsiteBanner::getEndTime, nowTime);
                    break;
                case INVALID:
                    //未生效 开始时间大于当前时间
                    queryWrapper.gt(CmsWebsiteBanner::getStartTime, nowTime);
                    break;
                default:
                    log.info("查询所有轮播图");
            }
        }

        Page<CmsWebsiteBanner> cmsWebsiteBannerPage = this.page(new Page<>(page, limit), queryWrapper);

        if (cmsWebsiteBannerPage.getTotal() == 0) {
            return new Page<>(page, limit);
        }

        Page<CmsWebsiteBannerVo> cmsWebsiteBannerVoPage = new Page<>(page, limit, cmsWebsiteBannerPage.getTotal());
        List<CmsWebsiteBannerVo> cmsWebsiteBannerList = cmsWebsiteBannerPage.getRecords().stream().map(this::conversionVo).collect(Collectors.toList());
        cmsWebsiteBannerVoPage.setRecords(cmsWebsiteBannerList);

        return cmsWebsiteBannerVoPage;
    }

    @Override
    public boolean update(CmsWebsiteBannerForm websiteBannerForm) {

        //校验ID
        CmsWebsiteBanner cmsWebsiteBannerOld = this.getById(websiteBannerForm.getId());
        if (ObjectUtils.isEmpty(cmsWebsiteBannerOld)) {
            throw new BizException("没有找到该数据！");
        }

        //校验与获取字典子项 banner位置信息
        SysDictItem sysDictItem = checkAndGetPosition(websiteBannerForm.getDictPositionTypeId());
        //校验上架时间 < 下架时间
        checkTime(websiteBannerForm);

        CmsWebsiteBanner article = conversionToPojo(websiteBannerForm);
        article.setId(cmsWebsiteBannerOld.getId());
        article.setDictPositionTypeId(sysDictItem.getId());

        return this.updateById(article);
    }

    @Override
    public boolean deleteByIds(List<String> asList) {
        if (CollectionUtils.isFull(asList)) {
            throw new BizException("没有选择任何数据，请重新操作！");
        }

        return this.removeByIds(asList);
    }

    @Override
    public boolean invalid(String id) {
        //校验id
        CmsWebsiteBanner cmsWebsiteBanner = this.getById(id);
        if (ObjectUtils.isEmpty(cmsWebsiteBanner)) {
            throw new BizException("没有此数据！");
        }

        //提前失效 将下架时间设置到当前时间的100毫秒
        Long invalidTime = System.currentTimeMillis() - 100L;
        if (invalidTime < cmsWebsiteBanner.getStartTime()) {
            invalidTime = cmsWebsiteBanner.getStartTime();
        }
        cmsWebsiteBanner.setEndTime(invalidTime);

        return this.updateById(cmsWebsiteBanner);
    }

    @Override
    public CmsWebsiteBannerVo detail(Integer id) {

        CmsWebsiteBanner cmsWebsiteBanner = this.getById(id);

        return conversionVo(cmsWebsiteBanner);
    }


    /**
     * ==================== 私有方法 =====================
     */

    private Page<HomePageWebsiteBannerVo> getWebsiteBannerPage(Integer page, Integer limit, Long dictPositionTypeId) {
        Page<CmsWebsiteBannerVo> cmsWebsiteBannerVoPage = this.pageList(page, limit, null, 1, dictPositionTypeId);

        Page<HomePageWebsiteBannerVo> homePageVoPage = new Page<>(cmsWebsiteBannerVoPage.getSize(), cmsWebsiteBannerVoPage.getTotal());
        if (cmsWebsiteBannerVoPage.getTotal() != 0) {
            List<HomePageWebsiteBannerVo> homePageVoList = conversionToHomePageVoList(cmsWebsiteBannerVoPage.getRecords());
            homePageVoPage.setRecords(homePageVoList);
        }
        return homePageVoPage;
    }

    private CmsWebsiteBannerVo conversionVo(CmsWebsiteBanner cmsWebsiteBanner) {
        if (ObjectUtils.isEmpty(cmsWebsiteBanner)) {
            return new CmsWebsiteBannerVo();
        }

        CmsWebsiteBannerVo cmsWebsiteBannerVo = new CmsWebsiteBannerVo();
        BeanUtil.copyProperties(cmsWebsiteBanner, cmsWebsiteBannerVo);

        //转换状态值
        long nowTime = System.currentTimeMillis();
        Long startTime = cmsWebsiteBanner.getStartTime();
        Long endTime = cmsWebsiteBanner.getEndTime();

        Integer showStatusCode = 0;
        //展示中 开始时间小于等于当前时间，结束时间大于当前时间
        if (startTime <= nowTime && endTime > nowTime) {
            showStatusCode = BannerShowStatusEnum.SHOWING.getCode();
        }
        //已过期 结束时间小于当前时间
        if (endTime < nowTime) {
            showStatusCode = BannerShowStatusEnum.EXPIRED.getCode();
        }
        //未生效 开始时间大于当前时间
        if (startTime > nowTime) {
            showStatusCode = BannerShowStatusEnum.INVALID.getCode();
        }
        cmsWebsiteBannerVo.setShowStatusCode(showStatusCode);

        //添加format的时间
        cmsWebsiteBannerVo.setStartTimeStr(new Date(startTime));
        cmsWebsiteBannerVo.setEndTimeStr(new Date(endTime));

        //添加
        SysDictItem sysDictItem = dictItemService.getDictItemById(cmsWebsiteBanner.getDictPositionTypeId());
        cmsWebsiteBannerVo.setDictPositionTypeNameCN(sysDictItem.getName());

        return cmsWebsiteBannerVo;
    }

    /**
     * 检查并获取字典项 banner位置信息
     */
    private SysDictItem checkAndGetPosition(Long dictPositionTypeId) {
        SysDictItem sysDictItem  = dictItemService.getDictItemById(dictPositionTypeId);
        if (ObjectUtils.isEmpty(sysDictItem)) {
            throw new BizException("所处位置类型参数错误");
        }

        return sysDictItem;
    }

    /**
     * 校验上架时间 < 下架时间
     */
    private void checkTime(CmsWebsiteBannerForm websiteBannerForm) {

        Long startTime = websiteBannerForm.getStartTime();
        Long endTime = websiteBannerForm.getEndTime();
        log.info("上架时间 = {}，下架时间 = {}", startTime, endTime);

        if (ObjectUtils.isEmpty(startTime)) {
            throw new BizException("上架时间参数为空");
        }
        if (ObjectUtils.isEmpty(endTime)) {
            throw new BizException("下架时间参数为空");
        }
        if (!checkTimeLength(websiteBannerForm.getStartTime(), CommonConstant.TIME_LENGTH_13)) {
            throw new BizException("上架时间参数 位数错误");
        }
        if (!checkTimeLength(websiteBannerForm.getEndTime(), CommonConstant.TIME_LENGTH_13)) {
            throw new BizException("下架时间参数 位数错误");
        }

        if (!(websiteBannerForm.getStartTime() < websiteBannerForm.getEndTime())) {
            throw new BizException("下架时间不能早于上架时间");
        }
    }

    /**
     * 检验时间位数
     */
    private Boolean checkTimeLength(@NonNull Long time, int timeLength) {
        if (ObjectUtils.isEmpty(time)) {
            return false;
        }

        if (time.toString().length() == timeLength) {
            return true;
        }

        return false;
    }

    private CmsWebsiteBanner conversionToPojo(CmsWebsiteBannerForm websiteBannerForm) {
        CmsWebsiteBanner cmsWebsiteBanner = new CmsWebsiteBanner();
        BeanUtil.copyProperties(websiteBannerForm, cmsWebsiteBanner);
        return cmsWebsiteBanner;
    }

    private List<HomePageWebsiteBannerVo> conversionToHomePageVoList(List<CmsWebsiteBannerVo> cmsWebsiteBannerVoList) {
        if (CollectionUtils.isEmpty(cmsWebsiteBannerVoList)) {
            return new ArrayList<>();
        }
        return cmsWebsiteBannerVoList.stream().map(this::conversionToHomePageVo).collect(Collectors.toList());
    }

    private HomePageWebsiteBannerVo conversionToHomePageVo(CmsWebsiteBannerVo cmsWebsiteBannerVo) {
        HomePageWebsiteBannerVo homePageWebsiteBannerVo = new HomePageWebsiteBannerVo();
        BeanUtil.copyProperties(cmsWebsiteBannerVo, homePageWebsiteBannerVo);
        return homePageWebsiteBannerVo;
    }

}
